﻿using Pdf2epub.ExtractStrategy;
using Pdf2epub.Interfaces;
using Pdf2epub.Model;
using System.IO;
using System.Linq;

namespace Pdf2epub.BusinessLogic.Extractors
{
    internal abstract class ExtractorBase : IExtractor
    {
        protected IProjectContext ProjectContext;

        protected ExtractorBase(IProjectContext projectContext)
        {
            ProjectContext = projectContext;
        }

        public ContentBlockCollection ContentBlocks { get; set; }

        public abstract int NumberOfPages { get; }

        public void CreateContentInContentCollection()
        {
            ClearImages();
            ClearImageCounter();
            ContentBlocks.Clear();

            for (int page = 1; page <= NumberOfPages; page++)
            {
                ExtractPage(page);
            }
        }

        public abstract Chapter[] ExtractDocumentOutline();

        protected virtual void ClearImageCounter()
        {
        }

        protected abstract ContentBlock[] Extract(int page);

        private void ClearImages()
        {
            if (!Directory.Exists(ProjectContext.ProjectConfiguration.ImageOutputPath))
                return;

            ProjectContext.FeedbackService.SetDetailText("Clearing old images");

            foreach (string file in Directory.GetFiles(ProjectContext.ProjectConfiguration.ImageOutputPath))
            {
                File.Delete(file);
            }
        }

        private void ExtractPage(int page)
        {
            if (PageIsExcluded(page))
                return;

            ProjectContext.FeedbackService.SetDetailText(string.Format("Extracting page {0}", page));

            bool coverImageFound = false;
            foreach (ContentBlock contentBlock in Extract(page))
            {
                if (!coverImageFound && ProjectContext.ProjectConfiguration.FirstImageElementIsCoverImage && page == 1)
                {
                    if (contentBlock.ContentType == ContentType.Image)
                    {
                        ProjectContext.ProjectConfiguration.CoverImagePath = contentBlock.Content;
                        coverImageFound = true;
                    }
                }
                contentBlock.SourcePage = page;

                ContentBlocks.Add(contentBlock);
            }
        }

        private bool PageIsExcluded(int page)
        {
            if (ProjectContext.ProjectConfiguration.ExcludedPages == null)
                return false;

            return ProjectContext.ProjectConfiguration.ExcludedPages.Any(range => (page >= range.StartPage) && (page <= range.EndPage));
        }
    }
}